package game;

import game.Data.RacaInfo;
import java.awt.Polygon;
import java.awt.Rectangle;
import java.awt.geom.*;
import java.awt.geom.Area;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Random;
import math.Point;
import saves.*;
import saves.Inventory.ItemEx;
import saves.items.Equipamento;
import saves.objects.Container;
import units.GameTime;

public class GalaxyGenerator {

    public static final float FACCOES_POR_RACA = 1.5f,
            IDIOMAS_POR_FACCAO = 1.1f, PORCENTAGEM_DE_RACIONALIDADE = 0.15f,
            CHANCE_DE_TER_PLANETAS = 0.8f, PLANETAS_POR_SISTEMA = 3f,
            TAMANHO_CORTE_BRACO = 0.1f, BRACOS_POR_GALAXIA = 6f, TAMANHO_GALAXIA = 30000,
            RAIO_PADRAO_ESTRELA = 25, //Em 10^-10 parsecs
            RAIO_PADRAO_PLANETA_TELURICO = 2.2f, PRESSAO_PADRAO_PLANETA_TELURICO = 50, //Em kPa
            RAIO_PADRAO_PLANETA_GASOSO = 4.7f, PRESSAO_PADRAO_PLANETA_GASOSO = 200,
            VEL_ROTACAO_PADRAO = 2, //Em 10^-5 pi*rad/s
            DISTANCIA_MEDIA_TELURICO = 50000, DISTANCIA_MEDIA_GASOSO = 700000; //Em 10^-10 parsec
    public static final String[] UNIDADE_DISTANCIA = {"parsec", "pc"};
    public static final long SISTEMAS_ESTELARES = 10000l,
            SISTEMAS_COM_VIDA = 5000l, RAIO_CENTRO = 4000l,
            MASSA_PADRAO_ESTRELA = 20000000000l, //Em 10^20 kg
            MASSA_PADRAO_PLANETA_TELURICO = 6000l,
            MASSA_PADRAO_PLANETA_GASOSO = 600000l,
            MASSA_PARA_TER_SATELITE = 7500l;
    private static final Random rand = new Random();
    private static int LAST_AREA;

    public static GalaxiaInicial gerarGalaxiaSimples() { // Gera somente um sistema para testar o jogo
        GalaxiaInicial r = new GalaxiaInicial();
        r.setTempoInicial(new GameTime());
        SistemaEstelar[] sis = new SistemaEstelar[1];
        Estrela[] estrelas = new Estrela[1];
        estrelas[0] = new Estrela("Sol", 2, 25, 200000);
        CorpoOrbitavel[] corpos = new CorpoOrbitavel[1];
        /*int[] area = new int[1];
        area[0] = 0;
        corpos[0] = new CorpoOrbitavel("Terra", 20, 0, 0, 0.00002f, 0.0001f, 1, area, new CorpoOrbitavel[0], estrelas);*/
        sis[0] = new SistemaEstelar("Solar", estrelas, corpos, new Point(0, 0));
        r.setSistemasEstelares(sis);
        r.setSistemaInicial(0);
        r.setCorpoInicial(0);
        r.setPontoInicial(new Point(20, 20));
        return r;
    }

    public static GalaxiaInicial gerarGalaxia(GalaxiaInicial parteEstatica) {
        class Setor {

            public Area area;
            public SistemaEstelar[] sistemas;
            public float p;

            public Setor(Area a, float p) {
                this.area = a;
                this.sistemas = null;
                this.p = p;
            }
        }

        GalaxiaInicial r = new GalaxiaInicial();

        /*
         * Gerar estrelas e planetas Obs. Todas as galáxias serão espirais
         */

        // Determinar número de braços
        //Usar n aqui para teste
        int qtosBracos = (int) (BRACOS_POR_GALAXIA + (rand.nextFloat() - 0.5f) * BRACOS_POR_GALAXIA / 4); //Mínimo 4!!!
        //Gerar dimensões da galáxia (em parsecs)
        //Usar 600 aqui para teste
        int raioGalaxia = (int) (TAMANHO_GALAXIA + (rand.nextFloat() - 0.5f) * TAMANHO_GALAXIA / 4);
        r.setPontoInicial(new Point(raioGalaxia / 2, raioGalaxia / 2));

        /*
         * Definição dos setores: 0: Núcleo (Super-denso) 1: Centro (Vai até separar os braços) Braço Interno e Externo de cada braço, nessa ordem.
         * Ver imagem para melhor descrição
         */

        @SuppressWarnings({"unchecked"})
        ArrayList<Setor>[] setores = new ArrayList[2 + 2 * qtosBracos];
        Area[] areas = new Area[2 + 2 * qtosBracos];

        //Gerar os sistemas fisicamente, para depois atribuir as facções
        //Usar 20 aqui para teste
        int raioNucleo = (int) (RAIO_CENTRO + (rand.nextFloat() - 0.5) * RAIO_CENTRO / 4);
        int raioCentro = (int) (0.2 * (raioGalaxia - raioNucleo)) + raioNucleo;

        Ellipse2D.Float nc = new Ellipse2D.Float(-raioNucleo, -raioNucleo, 2 * raioNucleo, 2 * raioNucleo);
        areas[0] = new Area(nc);

        Ellipse2D.Float ct = new Ellipse2D.Float(-raioCentro, -raioCentro, 2 * raioCentro, 2 * raioCentro);
        areas[1] = new Area(ct);
        areas[1].subtract(areas[0]);

        // Achar a elipse padrão
        Ellipse2D.Float elipsePadrao;
        float raioVertical;
        {
            Point p = new Point(0f, raioCentro);
            // Diametro maior:
            float pd = raioNucleo + (raioCentro - raioNucleo) / 2;
            float a = raioGalaxia + pd;
            Point cf = new Point(a / 2 - pd, 0f);
            // (x1 - x0)^2/a^2 + (y1-y0)^2/b^ = 1
            // Onde (x0, y0) é o centro, a é o raio horizontal e b é o raio vertical
            // Math.pow(p.x - centro.x, 2)/Math.pow(a, 2) + Math.pow(p.y/b) = 1
            raioVertical = 2 * ((float) Math.sqrt(Math.pow(p.y, 2) / (1 - Math.pow(p.x - cf.x, 2) / Math.pow(a / 2, 2))));
            elipsePadrao = new Ellipse2D.Float(cf.x - a / 2, cf.y - raioVertical / 2, a, raioVertical);
        }

        Point pi;
        {
            Iterator<Point2D> it = cib.util.geo.Geo2D.intersection(elipsePadrao, ct);            
            do
                pi = Point.rotacionarRad(new Point(it.next()), -2 * (float) Math.PI / qtosBracos);
            while ((it.hasNext()) && (pi.getX() < 0 || pi.getY() > 0));
        }

        Area braco = new Area(elipsePadrao);
        float rv = raioVertical * TAMANHO_CORTE_BRACO;
        braco.subtract(new Area(new Ellipse2D.Float(pi.x, pi.y - rv, raioGalaxia - pi.x, 2 * rv)));
        braco.subtract(new Area(new Rectangle2D.Float(-raioCentro, pi.y, raioGalaxia + raioCentro, raioGalaxia)));
        braco.subtract(areas[0]);
        braco.subtract(areas[1]);

        float rdd = (raioGalaxia + raioCentro);
        Area circuloCorte = new Area(new Ellipse2D.Float(-rdd / 2, -rdd / 2, rdd, rdd));

        areas[2] = (Area) braco.clone();
        areas[2].intersect(circuloCorte);

        areas[3] = (Area) braco.clone();
        areas[3].subtract(circuloCorte);

        AffineTransform aft = new AffineTransform();
        aft.rotate(2 * Math.PI / qtosBracos);

        for (int i = 4; i < areas.length - 1; i += 2) {
            areas[i] = areas[i - 2].createTransformedArea(aft);
            areas[i + 1] = areas[i - 1].createTransformedArea(aft);
        }

        /*
         *
         * Definir os setores de cada área
         *
         */

        //Núcleo
        setores[0] = new ArrayList<>();
        Area pc = new Area(new Ellipse2D.Float(-10, -10, 20, 20));
        setores[0].add(new Setor(pc, 0f)); //Ponto central

        Area css = (Area) areas[0].clone();
        css.subtract(pc);

        for (int i = 0; i < 4; i++) {
            Area qd = (Area) css.clone();
            switch (i) {
                case 0:
                    qd.intersect(new Area(new Rectangle2D.Float(0, -raioNucleo, raioNucleo, raioNucleo)));
                    break;
                case 1:
                    qd.intersect(new Area(new Rectangle2D.Float(0, 0, raioNucleo, raioNucleo)));
                    break;
                case 2:
                    qd.intersect(new Area(new Rectangle2D.Float(-raioNucleo, 0, raioNucleo, raioNucleo)));
                    break;
                case 3:
                    qd.intersect(new Area(new Rectangle2D.Float(-raioNucleo, -raioNucleo, raioNucleo, raioNucleo)));
                    break;
            }
            setores[0].add(new Setor(qd, 0.025f));
        }

        //Centro
        setores[1] = new ArrayList<>();
        Point pa, pn = new Point(0f, -raioGalaxia);
        float angulo = 2 * (float) Math.PI / qtosBracos;
        for (int i = 0; i < qtosBracos; i++) {
            pa = pn;
            pn = Point.rotacionarRad(pa, angulo);
            Area a = (Area) areas[1].clone();
            int[] xCoords = new int[3], yCoords = new int[3];
            xCoords[0] = 0;
            yCoords[0] = 0;
            xCoords[1] = (int) pa.x;
            yCoords[1] = (int) pa.y;
            xCoords[2] = (int) pn.x;
            yCoords[2] = (int) pn.y;
            a.intersect(new Area(new Polygon(xCoords, yCoords, 3)));
            setores[1].add(new Setor(a, 0.5f / qtosBracos));
        }

        //Braços
        for (int i = 0; i < qtosBracos; i++) {
            Area ant = new Area();
            setores[2 * i + 2] = new ArrayList<>();
            setores[2 * i + 3] = new ArrayList<>();
            for (int j = 0; j < 6; j++) {
                float raio = (j + 1) * (raioGalaxia - raioCentro) / 6 + raioCentro;
                Area a = new Area(new Ellipse2D.Float(-raio, -raio, raio * 2, raio * 2));
                Area nant = (Area) a.clone();
                a.subtract(ant);
                ant = nant;
                a.intersect(areas[2 + 2 * i + j / 3]);
                float coef;
                if (j == 0)
                    coef = 0.6f / qtosBracos;
                else if (j == 1)
                    coef = 0.5f / qtosBracos;
                else if (j == 5)
                    coef = 0.05f / (4 * qtosBracos);
                else
                    coef = (0.4f - 0.4f * j / 6) / qtosBracos;
                setores[2 + 2 * i + j / 3].add(new Setor(a, coef));
            }
        }

        /*
         *
         * Gerar os sistemas estelares
         *
         */

        LAST_AREA = 0; //Zerar o contador de áreas

        //Usar 500 aqui para teste TSTCHNG
        int qtosSistemas = (int) (SISTEMAS_ESTELARES * 0.9 + gerarInteiro(SISTEMAS_ESTELARES * 0.1f, 0) - SISTEMAS_ESTELARES * 0.05f); //Aprox.!
        for (int i = 0; i < setores.length; i++)
            for (int j = 0; j < setores[i].size(); j++)
                setores[i].get(j).sistemas = gerarSistemasEstelares((int) (qtosSistemas * setores[i].get(j).p * (1 + (rand.nextFloat() / 10))), setores[i].get(j).area);
        //^ Garante que não haverá dois sistemas na mesma posição

        //Adicionar os sistemas importantes
        if (parteEstatica != null && parteEstatica.getSistemasEstelares() != null) //H� sistemas importantes
            for (int i = 0; i < parteEstatica.getSistemasEstelares().length; i++) {
                //Preencher informações faltantes !! TODO !!

                //Achar o setor da galáxia
                int area, setor = 0;
                main:
                for (area = 0; area < setores.length; area++)
                    for (setor = 0; setor < setores[area].size(); setor++)
                        if (setores[area].get(setor).area.contains(new Point2D.Float(parteEstatica.getSistemasEstelares()[i].getPosicao().x, parteEstatica.getSistemasEstelares()[i].getPosicao().y)))
                            break main;

                //Ver se já existe uma estrela no setor
                int je = -1;
                for (int j = 0; j < setores[area].get(setor).sistemas.length; j++)
                    if (setores[area].get(setor).sistemas[j].getPosicao().equals(parteEstatica.getSistemasEstelares()[i].getPosicao())) {
                        je = i;
                        break;
                    }

                if (je != -1) //Já existe; substitui sistema anterior
                    setores[area].get(setor).sistemas[je] = parteEstatica.getSistemasEstelares()[i];
                else {
                    //Inserir no começo
                    SistemaEstelar[] nses = new SistemaEstelar[setores[area].get(setor).sistemas.length + 1];
                    nses[0] = parteEstatica.getSistemasEstelares()[i];
                    System.arraycopy(setores[area].get(setor).sistemas, 0, nses, 1, setores[area].get(setor).sistemas.length);
                }
            }

        ArrayList<SistemaEstelar> sistemas = new ArrayList<>();
        for (int i = 0; i < setores.length; i++)
            for (int j = 0; j < setores[i].size(); j++)
                sistemas.addAll(Arrays.asList(setores[i].get(j).sistemas));

        //TODO tirar! teste!
        Estrela sol = new Estrela("Sol", 3, 50, 50);
        sistemas.add(new SistemaEstelar("Sistema Solar", new Estrela[]{sol}, new CorpoOrbitavel[]{new CorpoOrbitavel(LAST_AREA, "Terra", 50, 50, 0, 1, Data.gerarGasesRandomicamente(), 0, 0.5f, 50000, 75000, 0, 0.5f, new CorpoCeleste[]{sol}, null, new CorpoOrbitavel.Info())}, new Point()));
        r.setSistemasEstelares(sistemas.toArray(new SistemaEstelar[sistemas.size()]));
        
        //Popular!
        
        // Gerar Naves

        // Gerar Você
        return r;
    }

    //Métodos numéricos
    public static int gerarInteiro(float media, int minimo) {
        int r = rand.nextInt((int) (2 * media));
        if (r < minimo)
            return minimo;
        return r;
    }

    public static float gerarFloat(float media, float variacao) {
        return (float) ((rand.nextFloat() - 0.5) * 2 * variacao + media);
    }

    public static float gerarFloatEntre(float i, float f) {
        return rand.nextFloat() * (f - i) + i;
    }

    public static SistemaEstelar[] gerarSistemasEstelares(int qtos, Area area) {
        SistemaEstelar[] r = new SistemaEstelar[qtos];
        for (int i = 0; i < qtos; i++) {
            boolean novo;
            do {
                r[i] = gerarSistemaEstelar(area);
                novo = false;
                for (int j = 0; !novo && j < i; j++)
                    if (r[j].getPosicao().equals(r[i].getPosicao())) {
                        novo = true; //Já existe um sistema nessa posição
                    }
            } while (novo);
        }
        return r;
    }

    //Sub métodos
    public static SistemaEstelar gerarSistemaEstelar(Area a) {
        //Achar posição
        Rectangle b = a.getBounds();
        Point2D.Float p;
        do {
            p = new Point2D.Float(gerarFloatEntre(b.x, b.x + b.width), gerarFloatEntre(b.y, b.y + b.height)); //área ficou ínfima
        } while (!a.contains(p));

        Estrela[] es = gerarEstrelas();
        return new SistemaEstelar(null, es, gerarCorposOrbitaveis(es), new Point(p));
    }

    public static Estrela[] gerarEstrelas() {
        int qtos = gerarInteiro(1.1f, 1);
        Estrela[] es = new Estrela[qtos];
        for (int i = 0; i < qtos; i++)
            es[i] = gerarEstrela();
        return es;
    }

    public static Estrela gerarEstrela() {
        float raio = gerarFloat(RAIO_PADRAO_ESTRELA, RAIO_PADRAO_ESTRELA / 3),
                massa = gerarFloat(MASSA_PADRAO_ESTRELA, raio / MASSA_PADRAO_ESTRELA);
        return new Estrela(null, Math.round(gerarFloat(Estrela.generateTipo(massa, raio), 1.5f)), raio, massa);
    }

    public static CorpoOrbitavel[] gerarCorposOrbitaveis(CorpoCeleste[] pai) {
        return gerarCorposOrbitaveis(pai, gerarInteiro(PLANETAS_POR_SISTEMA, 0));
    }

    public static CorpoOrbitavel[] gerarCorposOrbitaveis(CorpoCeleste[] pai, int qtos) {
        CorpoOrbitavel[] r = new CorpoOrbitavel[qtos];
        for (int i = 0; i < r.length; i++)
            r[i] = gerarPlaneta(pai);
        return r;
    }

    public static CorpoOrbitavel gerarPlaneta(CorpoCeleste[] pai) {
        //Determinar se será telúrico, gasoso ou an�o:
        int tipo;
        float massa, raio, pressao;
        float rh1, rh2; //Sobre a órbita
        double t = Math.random();
        if (t < 0.5) {
            tipo = 0; //Tel�rico
            raio = gerarFloat(RAIO_PADRAO_PLANETA_TELURICO, RAIO_PADRAO_PLANETA_TELURICO / 5);
            massa = gerarFloat(MASSA_PADRAO_PLANETA_TELURICO, raio / MASSA_PADRAO_PLANETA_TELURICO);
            pressao = gerarFloat(PRESSAO_PADRAO_PLANETA_TELURICO, PRESSAO_PADRAO_PLANETA_TELURICO / 2);

            //Dist�ncia pequena, excentricidade pequena
            rh1 = gerarFloat(DISTANCIA_MEDIA_TELURICO, DISTANCIA_MEDIA_TELURICO / 3);
            rh2 = rh1 * (1 + 0.01f + (float) Math.random() / 100 + 1 / 200);
        } else if (t < 0.9) {
            tipo = 1; //Gasoso
            raio = gerarFloat(RAIO_PADRAO_PLANETA_GASOSO, RAIO_PADRAO_PLANETA_GASOSO / 5);
            massa = gerarFloat(MASSA_PADRAO_PLANETA_GASOSO, raio / MASSA_PADRAO_PLANETA_GASOSO);
            pressao = gerarFloat(PRESSAO_PADRAO_PLANETA_GASOSO, PRESSAO_PADRAO_PLANETA_GASOSO / 2);

            //Dist�ncia grande, excentricidade pequena
            rh1 = gerarFloat(DISTANCIA_MEDIA_GASOSO, DISTANCIA_MEDIA_GASOSO / 3);
            rh2 = rh1 * (1 + 0.01f + (float) Math.random() / 100 + 1 / 200);
        } else {
            tipo = 0; //An�o
            raio = gerarFloat(RAIO_PADRAO_PLANETA_TELURICO / 10, RAIO_PADRAO_PLANETA_TELURICO / 5);
            massa = gerarFloat(MASSA_PADRAO_PLANETA_TELURICO / 10, raio / MASSA_PADRAO_PLANETA_TELURICO);
            pressao = gerarFloat(PRESSAO_PADRAO_PLANETA_TELURICO / 10, PRESSAO_PADRAO_PLANETA_TELURICO / 20);

            //Dist�ncia grande, mas variada, excentricidade grande
            rh1 = gerarFloat(DISTANCIA_MEDIA_GASOSO, DISTANCIA_MEDIA_GASOSO / 2);
            rh2 = rh1 * (1 + 0.2f + (float) Math.random() / 100 + 1 / 200);
        }

        //Args: nome, massa, raio, pressaoMedia, double[] gasesAtmosfericos, velAngRot, anguloEixoTranslacao, rh1, rh2, rv, angRot, angTrans, CorpoCeleste[] pai, CorpoOrbitavel[] filhos
        CorpoOrbitavel c = new CorpoOrbitavel(LAST_AREA++, null, massa, raio, tipo, pressao, Data.gerarGasesRandomicamente(), gerarFloat(VEL_ROTACAO_PADRAO, VEL_ROTACAO_PADRAO / 5), gerarFloat((float) (1 / 9), (float) (1 / 18)), rh1, rh2, gerarFloatEntre(0, 2), gerarFloatEntre(0, 2), pai, null, new CorpoOrbitavel.Info());

        //Determinar se terá satélites ou não
        if (Math.random() < massa / MASSA_PARA_TER_SATELITE || Math.random() < 0.01) {
            //Tem satélites
            int qtos = 1;
            float chance = 0.5f;
            while (Math.random() < chance) {
                qtos++;
                chance /= 2;
            }

            CorpoOrbitavel[] filhos = new CorpoOrbitavel[qtos];
            for (int i = 0; i < qtos; i++)
                filhos[i] = gerarSatelite(new CorpoOrbitavel[]{c}, rh1, raio, massa, 1);
            c.setFilhos(filhos);
        }

        return c;
    }

    public static CorpoOrbitavel gerarSatelite(CorpoCeleste[] pai, float distanciaPai, float raioPai, float massaPai, int nivel) {
        //Determinar se será telúrico, gasoso ou anão:
        float raio = gerarFloat(raioPai / 10, raioPai / 5);
        float massa = gerarFloat(massaPai / 10, raio / massaPai);
        float pressao = gerarFloat(PRESSAO_PADRAO_PLANETA_TELURICO / 10, PRESSAO_PADRAO_PLANETA_TELURICO / 20);

        //Distância grande, mas variada, excentricidade grande
        float rh1 = gerarFloat(distanciaPai / 10, distanciaPai / 20);
        float rh2 = rh1 * (1 + 0.1f + (float) Math.random() / 100 + 1 / 200);

        //Args: nome, massa, raio, pressaoMedia, double[] gasesAtmosfericos, velAngRot, anguloEixoTranslacao, rh1, rh2, rv, angRot, angTrans, CorpoCeleste[] pai, CorpoOrbitavel[] filhos
        CorpoOrbitavel c = new CorpoOrbitavel(LAST_AREA++, null, massa, raio, 0, pressao, Data.gerarGasesRandomicamente(), gerarFloat(VEL_ROTACAO_PADRAO, VEL_ROTACAO_PADRAO / 5), gerarFloat((float) (1 / 9), (float) (1 / 18)), rh1, rh2, gerarFloatEntre(0, 2), gerarFloatEntre(0, 2), pai, null, new CorpoOrbitavel.Info());

        //Determinar se terá satélites ou não
        if (Math.random() < 0.01 / (Math.pow(10, nivel))) {
            nivel++;

            //Tem satélites
            int qtos = 1;
            float chance = 0.1f;
            while (Math.random() < chance) {
                qtos++;
                chance /= 10;
            }

            CorpoOrbitavel[] filhos = new CorpoOrbitavel[qtos];
            for (int i = 0; i < qtos; i++)
                filhos[i] = gerarSatelite(new CorpoOrbitavel[]{c}, rh1, raio, massa, nivel);
            c.setFilhos(filhos);
        }

        return c;
    }

    public static Faccao gerarFaccao(RacaInfo raca) {
        return null;
    }

    public static saves.Area[] gerarAreas(String caminho, CorpoOrbitavel c) {
        saves.Area[] a = new saves.Area[1];
        a[0] = new saves.Area(gerarMatrizArea());
        a[0].updateSubBlocos();
        ArrayList<ItemEx> lst = new ArrayList<>();
        lst.add(new ItemEx(new Equipamento(3, 0, 1, .5f), 1));
        a[0].addObjeto(new Container(150, 150, 0, lst, 500, a[0].getWorld()));
        a[0].addObjeto(new Container(30, 48, 0, new ArrayList<ItemEx>(), 10, a[0].getWorld()));
        a[0].addObjeto(new Container(40, 48, 0, new ArrayList<ItemEx>(), 0, a[0].getWorld()));
        return a;
    }
    
    public static BlocoSimples[][] gerarMatrizArea() {
        BlocoSimples[][] bs = new BlocoSimples[200][200];
        for (int i = 0; i < bs.length; i++)
            for (int j = 0; j < bs[i].length; j++)
                if (j == 0 || i == 0 || j == 151 || i == 131 || j == 150 || i == 130)
                    bs[i][j] = BlocoSimples.getBloco(2);
                else
                    bs[i][j] = BlocoSimples.getBloco(1);
        /*((BlocoSimples.Complexo) bs[5][2]).setConexao(2, true);
        
        ((BlocoSimples.Complexo) bs[5][3]).setConexao(0, true);
        ((BlocoSimples.Complexo) bs[5][3]).setConexao(2, true);
        ((BlocoSimples.Complexo) bs[5][3]).setConexao(3, true);
        
        ((BlocoSimples.Complexo) bs[4][3]).setConexao(1, true);
        ((BlocoSimples.Complexo) bs[4][3]).setConexao(3, true);
        
        ((BlocoSimples.Complexo) bs[3][3]).setConexao(1, true);
        
        ((BlocoSimples.Complexo) bs[5][4]).setConexao(0, true);
        ((BlocoSimples.Complexo) bs[5][4]).setConexao(2, true);
        ((BlocoSimples.Complexo) bs[5][4]).setConexao(1, true);
        
        ((BlocoSimples.Complexo) bs[5][5]).setConexao(0, true);
        ((BlocoSimples.Complexo) bs[5][5]).setConexao(2, true);
        
        ((BlocoSimples.Complexo) bs[5][6]).setConexao(0, true);
        
        ((BlocoSimples.Complexo) bs[6][4]).setConexao(3, true);
        ((BlocoSimples.Complexo) bs[6][4]).setConexao(1, true);
        
        ((BlocoSimples.Complexo) bs[7][4]).setConexao(3, true);
        ((BlocoSimples.Complexo) bs[7][4]).setConexao(2, true);
        
        ((BlocoSimples.Complexo) bs[7][5]).setConexao(0, true);
        ((BlocoSimples.Complexo) bs[7][5]).setConexao(3, true);
        
        ((BlocoSimples.Complexo) bs[6][5]).setConexao(1, true);*/
        
        /*for (int i = 0; i < bs.length; i++)
            for (int j = 0; j < bs[i].length; j++)
                if (bs[i][j] instanceof BlocoSimples.Complexo)
                    ((BlocoSimples.Complexo) bs[i][j]).setEletrocutado(true);*/
        return bs;
    }
}